package com.njtoyo.taxi.admin.service.business.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Dict;
import cn.hutool.core.lang.UUID;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.conditions.update.LambdaUpdateChainWrapper;
import com.njtoyo.taxi.admin.library.Const;
import com.njtoyo.taxi.admin.library.common.Enum;
import com.njtoyo.taxi.admin.library.common.OperationRecordHelper;
import com.njtoyo.taxi.admin.library.common.util.CopyUtil;
import com.njtoyo.taxi.admin.library.taxi_service.SimpleCallTaxiService;
import com.njtoyo.taxi.admin.library.taxi_service.dto.SimpleCallSendAppointment;
import com.njtoyo.taxi.admin.mapper.master.entity.*;
import com.njtoyo.taxi.admin.mapper.master.enums.*;
import com.njtoyo.taxi.admin.mapper.master.enums.SimpleCallRideState;
import com.njtoyo.taxi.admin.mapper.master.mapper.*;
import com.njtoyo.taxi.admin.rest.presenter.business.simple_call.backlog.InitRecordListPresenter;
import com.njtoyo.taxi.admin.rest.presenter.platfrom.AdminUserIdentityPresenter;
import com.njtoyo.taxi.admin.rest.wrapper.business.simple_call.backlog.*;
import com.njtoyo.taxi.admin.service.business.SimpleCallBacklogService;
import com.njtoyo.taxi.admin.utils.AuthUtil;
import com.taxi.entity.common.RestResult;
import com.taxi.entity.common.ResultEnum;
import com.njtoyo.taxi.entity.backend.AdminUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.Function;
import java.util.stream.Collectors;

@Component
@DS(Const.PRIMARY_DS)
public class SimpleCallBacklogServiceImpl implements SimpleCallBacklogService {

    @Autowired
    private SimpleCallBacklogMapper simpleCallBacklogMapper;

    @Autowired
    private SimpleCallTaxiService simpleCallTaxiService;

    @Autowired
    private OperationRecordHelper operationRecordHelper;
    @Autowired
    private GeoAreaMapper geoAreaMapper;
    @Autowired
    private TaxiMapper taxiMapper;
    @Autowired
    private SimpleCallMapper simpleCallMapper;
    @Autowired
    private SimpleCallRideMapper simpleCallRideMapper;
    @Autowired
    private SimpleCallCustomerMapper simpleCallCustomerMapper;
    @Autowired
    private CallRelevanceMapper callRelevanceMapper;
    @Autowired
    private DriverMapper driverMapper;
    @Autowired
    private SimpleCallDiagramMapper simpleCallDiagramMapper;

    @Override
    public RestResult<List<InitRecordListPresenter>> getInitRecord(AdminUser adminUser, GetInitRecordWrapper wrapper) {
        QueryWrapper<SimpleCallBacklog> queryWrapper = new QueryWrapper<>();
        queryWrapper.gt(Objects.nonNull(wrapper.getLastId()), "id", wrapper.getLastId())
                .eq("state", SimpleCallBacklogState.init);
        if (!adminUser.getAccountType().equals(com.njtoyo.taxi.entity.backend.Enum.AccountType.platform)) {
            AdminUserIdentityPresenter identity = (AdminUserIdentityPresenter) adminUser.getIdentity();
            queryWrapper.in("area_id", identity.getAreaIds());
        }
        List<SimpleCallBacklog> result = simpleCallBacklogMapper.selectList(queryWrapper);

        List<InitRecordListPresenter> res = CopyUtil.copyList(result, InitRecordListPresenter.class);

        return RestResult.success(res);
    }

    @Override
    public RestResult update(AdminUser adminUser, Long id, UpdateOriginWrapper wrapper) {
        SimpleCallBacklog backlog = simpleCallBacklogMapper.selectById(id);
        if (Objects.isNull(backlog)) {
            return RestResult.build(ResultEnum.NOT_FOUND);
        }
        if (!backlog.getState().equals(SimpleCallBacklogState.init)) {
            return RestResult.build(ResultEnum.SIMPLE_CALL_BACKLOG_DONE);
        }
        SimpleCallBacklog updateWrapper = new SimpleCallBacklog();
        updateWrapper.setId(id)
                .setOrigin(wrapper.getOrigin())
                .setOriginName(wrapper.getOriginName())
                .setOriginPlaceName(wrapper.getOriginPlaceName());

        simpleCallBacklogMapper.updateById(updateWrapper);

        return RestResult.success();
    }

    @Override
    public RestResult send(AdminUser adminUser, Long id, SendWrapper wrapper) {
        SimpleCallBacklog backlog = simpleCallBacklogMapper.selectById(id);
        if (Objects.isNull(backlog)) {
            return RestResult.build(ResultEnum.NOT_FOUND);
        }
        if (!backlog.getState().equals(SimpleCallBacklogState.init)) {
            return RestResult.build(ResultEnum.SIMPLE_CALL_BACKLOG_DONE);
        }
        // 坐标发送，则判断坐标不能为空
        if (wrapper.getSendType().equals(Enum.SimpleCallSendType.coordinates) &&
                (Objects.isNull(backlog.getOrigin()) || Objects.isNull(backlog.getOriginPlaceName()) || Objects.isNull(backlog.getOriginName()))) {
            return RestResult.failed("坐标为空无法发送");
        }

        Map<String, Object> requestBody = new HashMap<>();
        requestBody.put("adCode", backlog.getAdCode());
        requestBody.put("mobileNumber", backlog.getMobileNumber());
        requestBody.put("url", backlog.getAudioUrl());
        if (Objects.nonNull(backlog.getAreaIds())) {
            requestBody.put("areaIds", backlog.getAreaIds());
        }

        if (wrapper.getSendType().equals(Enum.SimpleCallSendType.coordinates)) {
            Map<String, Object> coordinate = new HashMap<>();
            coordinate.put("longitude", backlog.getOrigin().getLongitude());
            coordinate.put("latitude", backlog.getOrigin().getLatitude());
            Map<String, Object> origin = new HashMap<>();
            origin.put("coordinate", coordinate);
            origin.put("name", backlog.getOriginName());
            origin.put("placeName", backlog.getOriginPlaceName());
            requestBody.put("origin", origin);
        }

        // 发单
        Long callId = simpleCallTaxiService.send(requestBody);
        if (Objects.isNull(callId)) {
            return RestResult.build(ResultEnum.SIMPLE_CALL_SEND_FAILED);
        }
        new LambdaUpdateChainWrapper<>(simpleCallBacklogMapper)
                .eq(SimpleCallBacklog::getId, id)
                .set(SimpleCallBacklog::getCallId, callId)
                .set(SimpleCallBacklog::getState, SimpleCallBacklogState.done)
                .update();

        operationRecordHelper.addBusinessLog(String.format("发送电召单 [%s] 发单形式: %s", backlog.getId(), wrapper.getSendType().name()));
        return RestResult.success();
    }

    @Override
    public RestResult cancel(AdminUser adminUser, Long id, CancelWrapper wrapper) {
        SimpleCallBacklog backlog = simpleCallBacklogMapper.selectById(id);
        if (Objects.isNull(backlog)) {
            return RestResult.build(ResultEnum.NOT_FOUND);
        }
        if (!backlog.getState().equals(SimpleCallBacklogState.init)) {
            return RestResult.build(ResultEnum.SIMPLE_CALL_BACKLOG_DONE);
        }
        new LambdaUpdateChainWrapper<>(simpleCallBacklogMapper)
                .eq(SimpleCallBacklog::getId, id)
                .set(SimpleCallBacklog::getState, SimpleCallBacklogState.cancel)
                .update();

        operationRecordHelper.addBusinessLog(String.format("取消了电召单 [%s]", backlog.getId()));

        if (wrapper.getSendMsg()) {
            simpleCallTaxiService.sendCancelMsg(backlog);
        }

        return RestResult.success();
    }

    @Override
    public RestResult<?> sendPhone(AdminUser adminUser, SendPhoneWrapper wrapper) {
        QueryWrapper<GeoArea> areaWrapper = new QueryWrapper<>();
        areaWrapper.eq("ad_code", wrapper.getAdCode());
        GeoArea area = geoAreaMapper.selectOne(areaWrapper);
        if (Objects.isNull(area)) {
            return RestResult.failed("区域未开通");
        }

        Map<String, Object> requestBody = new HashMap<>();
        //乘客标签
        String tags = wrapper.getTag();
        if (StrUtil.isNotBlank(tags)) {
            requestBody.put("customerTagCategory", "old_people");

        }
        if (CallMode.appoint == wrapper.getCallMode() && StrUtil.isNotBlank(wrapper.getTaxiId())) {
            Taxi taxi = taxiMapper.selectOne(Wrappers.<Taxi>lambdaQuery().eq(Taxi::getId, wrapper.getTaxiId()));
            if (ObjectUtil.isNull(taxi)) {
                return RestResult.failed("指定车辆下发失败,车辆已不存在!");
            }
            if (!taxi.getIsAvailable()) {
                return RestResult.failed("指定车辆下发失败,当前出租车载客中或者未出车!");
            }
            requestBody.put("taxiId", wrapper.getTaxiId());
        } else if (CallMode.love == wrapper.getCallMode() && StrUtil.isNotBlank(wrapper.getTaxiId())) {
            requestBody.put("taxiId", wrapper.getTaxiId());
        }
        if (StrUtil.isNotBlank(wrapper.getTaxiId()) && "appointment".equals(wrapper.getCallType()) &&
                CallMode.appoint == wrapper.getCallMode()) {
            Driver driver = driverMapper.selectOne(Wrappers.<Driver>lambdaQuery()
                    .eq(Driver::getTaxiId, wrapper.getTaxiId())
                    .eq(Driver::getInService, true));
            if (ObjectUtil.isNull(driver)) {
                return RestResult.failed("发单失败,此司机未出车!");

            }
            if (driver.getAcceptCallCtg() == DriverAcceptCallCtg.onlyRealtime) {
                return RestResult.failed("发单失败,此司机当前不接预约单!");
            }
            List<Taxi> taxis = simpleCallDiagramMapper.getAppointmentTaxi();
            if (CollUtil.isNotEmpty(taxis)) {
                Map<Long, Taxi> taxiMap = taxis.stream().collect(Collectors.toMap(Taxi::getId, Function.identity()));
                Long taxiId = Convert.toLong(wrapper.getTaxiId());
                if (ObjectUtil.isNotNull(taxiMap.get(taxiId))) {
                    return RestResult.failed("发单失败,此司机当前有未完成的预约单!");
                }

            }
        }
        requestBody.put("adCode", wrapper.getAdCode());
        requestBody.put("adminId", AuthUtil.getUserInfo().getId());
        requestBody.put("mobileNumber", wrapper.getMobileNumber());
        requestBody.put("url", null);
        Map<String, Object> coordinate = new HashMap<>();
        coordinate.put("longitude", wrapper.getOrigin().getLongitude());
        coordinate.put("latitude", wrapper.getOrigin().getLatitude());
        Map<String, Object> origin = new HashMap<>();
        origin.put("coordinate", coordinate);
        origin.put("name", wrapper.getOriginName());
        origin.put("placeName", wrapper.getOriginPlaceName());
        requestBody.put("origin", origin);

        if (NumberUtil.compare(wrapper.getDestination().getLongitude(), Double.valueOf("0.0")) != 0 &&
                NumberUtil.compare(wrapper.getDestination().getLatitude(), Double.valueOf("0.0")) != 0) {
            //目的地
            Map<String, Object> destinationMap = new HashMap<>();
            //目的地 坐标
            Map<String, Object> destinationCoordinate = new HashMap<>();
            destinationCoordinate.put("longitude", wrapper.getDestination().getLongitude());
            destinationCoordinate.put("latitude", wrapper.getDestination().getLatitude());
            destinationMap.put("coordinate", destinationCoordinate);
            destinationMap.put("name", wrapper.getDestinationName());
            destinationMap.put("placeName", wrapper.getDestinationPlaceName());
            requestBody.put("destination", destinationMap);
            System.out.println(JSON.toJSONString(requestBody));
        }
        Long callId = null;
        if ("realTime".equals(wrapper.getCallType())) {
            callId = simpleCallTaxiService.send(requestBody);
        } else {
            SimpleCallSendAppointment sendAppointment = JSON.parseObject(JSON.toJSONString(requestBody), SimpleCallSendAppointment.class);
            sendAppointment.setScheduleTime(DateUtil.parseDateTime(wrapper.getUseTaxiTime()).getTime() / 1000);
            callId = simpleCallTaxiService.sendAppointment(sendAppointment);
        }

        if (Objects.isNull(callId)) {
            return RestResult.build(ResultEnum.SIMPLE_CALL_SEND_FAILED);
        }
        //修改更改呼叫模式
        SimpleCall simpleCall = new SimpleCall();
        simpleCall.setId(callId);
        simpleCall.setCallMode(wrapper.getCallMode());
        simpleCallMapper.updateById(simpleCall);


        SimpleCallBacklog backlog = new SimpleCallBacklog();
        backlog.setMobileNumber(wrapper.getMobileNumber())
                .setAreaId(area.getId())
                .setAdCode(area.getAdCode())
                .setMappingId(0L)
                .setOrigin(wrapper.getOrigin())
                .setOriginName(wrapper.getOriginName())
                .setOriginPlaceName(wrapper.getOriginPlaceName())
                .setCallId(callId)
                .setAudioUrl(null)
                .setAudioUrlMd5(SecureUtil.md5(UUID.randomUUID().toString()))
                .setState(SimpleCallBacklogState.done);
        simpleCallBacklogMapper.insert(backlog);

        operationRecordHelper.addBusinessLog(String.format("发送电召单 [%s] 发单形式: coordinates", backlog.getId()));
        return RestResult.success();
    }

    @Override
    public RestResult sendMsg(Long id, Dict params) {
        Integer type = params.getInt("type");
        SimpleCall simpleCall = simpleCallMapper.selectById(id);
        SimpleCallCustomer simpleCallCustomer = simpleCallCustomerMapper.selectById(simpleCall.getCustomerId());
        Dict dictMap = new Dict();
        if (type == 0) {//无人接单通知
            if (simpleCall.getCategory() == SimpleCallRideCategory.phone_appointment) {
                simpleCallTaxiService.sendMsg(simpleCallCustomer.getMobileNumber(), "SMS_465980785", "");
            } else {
                simpleCallTaxiService.sendMsg(simpleCallCustomer.getMobileNumber(), "SMS_465565259", "");
            }
        } else if (type == 1) {//提醒乘客上车
            SimpleCallRide simpleCallRide = simpleCallRideMapper.selectOne(Wrappers.<SimpleCallRide>lambdaQuery().eq(SimpleCallRide::getRefId, id));
            if (ObjectUtil.isNull(simpleCallRide)) {
                return RestResult.failed("行程不存在");
            }
            Taxi taxi = taxiMapper.selectById(simpleCallRide.getTaxiId());
            dictMap.put("license_plate_number", taxi.getPlateNumber());
            dictMap.put("time", DateUtil.formatDateTime(simpleCall.getScheduleTime()));
            dictMap.put("address", simpleCall.getOriginName());

            simpleCallTaxiService.sendMsg(simpleCallCustomer.getMobileNumber(), "SMS_465580314", JSON.toJSONString(dictMap));
        } else if (type == 2) {//提醒乘客叫车成功
            SimpleCallRide simpleCallRide = simpleCallRideMapper.selectOne(Wrappers.<SimpleCallRide>lambdaQuery().eq(SimpleCallRide::getRefId, id));
            if (ObjectUtil.isNull(simpleCallRide)) {
                return RestResult.failed("行程不存在");
            }
            Taxi taxi = taxiMapper.selectById(simpleCallRide.getTaxiId());
            CallRelevance callRelevance = callRelevanceMapper.selectOne(Wrappers.<CallRelevance>lambdaQuery()
                    .eq(CallRelevance::getSimpleCallRideId, simpleCallRide.getId())
                    .eq(CallRelevance::getIsEffective, true));
            dictMap.put("license_plate_number", taxi.getPlateNumber());
            String phone = "";
            if (ObjectUtil.isNotNull(callRelevance)) {
                dictMap.put("phone", callRelevance.getRelationNumber());
                phone = callRelevance.getRelationNumber();
            } else {
                Driver driver = driverMapper.selectById(simpleCallRide.getDriverId());
                dictMap.put("phone", driver.getMobileNumber());
                phone = driver.getMobileNumber();
            }
            if (simpleCall.getCategory() == SimpleCallRideCategory.phone_appointment) {
                simpleCallTaxiService.sendMsg(simpleCallCustomer.getMobileNumber(), "SMS_465885797", JSON.toJSONString(Dict.create()
                        .set("license_plate_number", taxi.getPlateNumber())
                        .set("time", DateUtil.formatDateTime(simpleCall.getScheduleTime()))
                        .set("driver_tel", phone)
                        .set("service_tel", "95128")));
            } else {
                simpleCallTaxiService.sendMsg(simpleCallCustomer.getMobileNumber(), "SMS_465675116", JSON.toJSONString(dictMap));
            }

        }
        return RestResult.success();
    }
}
